/*
 * Copyright 2007-2009 Perttu "celeron55" Ahola <celeron55@gmail.com>
 *
 * This file is part of jukumagic.
 *
 * jukumagic is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * jukumagic is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with jukumagic.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef JUKUOBJECT_H_
#define JUKUOBJECT_H_

#include "tinyxml/tinyxml.h"
#include "wx/wx.h"
#include "boardpoint.h"
#include <list>
#include <assert.h>

#define OBJECT_ID_INVALID -1

enum JukuObjectType
{
	TYPE_UNKNOWN,
	TYPE_OBJECTCONTAINER,
	TYPE_XML,
	TYPE_PROJECT,
	TYPE_BOARD,
	TYPE_JUMPER_WIRE,
	TYPE_COMPONENT,
	TYPE_FOOTPRINT,
	TYPE_PIN,
	TYPE_RECT,
	TYPE_ARC,
	TYPE_LINE,
	TYPE_FOOTPRINTLIBRARYNODE,
	TYPE_CUT,
	TYPE_NARROWCUT,
	TYPE_NETLIST,
	TYPE_NET,
	TYPE_NETCOMPONENT,
	//TYPE_COUNT
};

enum TurnDirection
{
	CCW,
	CW
};

enum ObjectChangeType
{
	OBJECT_CHANGE_UNKNOWN,
	OBJECT_CHANGE_SELECTION,
	OBJECT_CHANGE_CONTENTS,
};

/*inline const char * ObjectChangeTypeString(ObjectChangeType type)
{
	switch(type){
	case OBJECT_CHANGE_UNKNOWN: return "OBJECT_CHANGE_UNKNOWN";
	case OBJECT_CHANGE_SELECTION: return "OBJECT_CHANGE_SELECTION";
	case OBJECT_CHANGE_CONTENTS: return "OBJECT_CHANGE_CONTENTS";
	}
	return "[INVALID]";
}*/

#define JUKUOBJECT_SELECTED (1<<0)
#define JUKUOBJECT_AUTOMATIC (1<<1)

#define JUKUOBJECT_INITIAL_FLAGS 0

class JukuObject
{
private:
	int m_flags;
protected:
	void ReportChange(ObjectChangeType type){ SelfChanged(type); if(m_owner) m_owner->ChildChanged(type, this); }
	
	// Override to read change events
	virtual void ChildChanged(ObjectChangeType type, JukuObject *obj){}
	virtual void SelfChanged(ObjectChangeType type){}
public:
	//int m_id;
	JukuObject *m_owner;
	JukuObject();
	virtual ~JukuObject();
	
	virtual JukuObjectType GetType(){ return TYPE_UNKNOWN; }
    virtual const wxChar * GetShortString(void){return NULL;}
	virtual const wxChar * GetTypeString(void){return _("Unknown");}
 	virtual JukuObject* MakeACopy(){ assert(0);return NULL; }
	virtual void WriteXML(TiXmlNode* root){}

	virtual void WriteBaseXML(TiXmlElement *element);
	virtual void ReadBaseXML(TiXmlElement *element);

	//virtual void Remove(JukuObject* object){}
	//virtual bool Add(JukuObject* object, JukuObject *prev_object){ object->m_owner = this; return true; }
	virtual bool Add(JukuObject* object, JukuObject *prev_object);
	/*
		- dc: wxDC on which to draw. If the window is scrolled, origin should be (0,0).
		- window: window on which to check IsExposed(). if NULL, everything should be drawn
		- origin: the origin of the object, in logical units. Add to coordinates when drawing or using IsExposed.

		When checking window->IsExposed(), run the coordinates through dc.LogicalToDeviceXRel() and dc.LogicalToDeviceYRel() functions
	*/
	virtual void Draw(wxDC &dc, wxWindow *window, wxPoint origin){}
	virtual BoardRect GetDrawArea(){ return BoardRect(0,0,0,0); }
	virtual void Move(int dx, int dy){}
	
	virtual int GetSide(){return 0;}
	// x and y are relative to parent origin
	virtual bool IsSelectedInPoint(int x, int y){return false;}
	virtual bool IsSelectedInArea(int x1, int y1, int x2, int y2, bool touch_is_enough)
			{return false;}
	
	virtual void SetSelected(bool selected);
	virtual void SetSelectedSilent(bool selected);
	bool GetSelected(){return m_flags & JUKUOBJECT_SELECTED;}

	void SetAutomatic(bool automatic){ if(automatic) m_flags |= JUKUOBJECT_AUTOMATIC; else m_flags &= ~JUKUOBJECT_AUTOMATIC; }
	bool GetAutomatic(){ return m_flags & JUKUOBJECT_AUTOMATIC; }

	virtual BoardRect GetPinExtents(){return BoardRect(0,0,0,0);}

	virtual void Rotate(TurnDirection dir, BoardPoint origin){}
	
	static void PrintList(std::list<JukuObject*> &objects);
};


#endif

